const redisClient = require('../redis/redisClient');
const errors = require('./error');
const ResourceId = require('./api/ResourceId');
const Stop = require('./api/Stop');
const Start = require('./api/Start');
const Query = require('./api/Query');
const ReTryTimesOutError = require('./ReTryTimesOutError');
const logger = require('../utils').getLogger(__filename);
const _ = require('lodash')
const config = require('config');
const agora = config.get('agora')
const prefix = config.get('aliyun.storageConfig.fileNamePrefix')[0]
const exitStatus = [6, 7, 8, 20]

class Recorder {
	constructor(args, modal, clientRequest) {
		this.logger = logger;
		this.modal = modal ? modal : 'mix';
		this.clientRequest = clientRequest;
		this._startTimeOut = {}
		this.prefix = prefix
		this.args = args
	}

	createMeetingInfo(obj) {
		return Object.assign({}, this.args, obj)
	}

	async start(clientRequest) {
		let { channelName, meetingId, uid, type } = this.args
		let rid = await redisClient.getUID(meetingId);
		let recource = new ResourceId({ channelName, rid });
		let resourceId = await recource.run();
		clientRequest = _.defaultsDeep({}, clientRequest, this.clientRequest)
		let starter = new Start({
			channelName,
			rid,
			uid,
			type,
			resourceId,
			clientRequest
		}, this.modal);
		let ret = await starter.run();
		return ret;
	}

	async stop() {
		let { channelName, meetingId, uid } = this.args
		let info = await this.getMeetingInfo(meetingId, uid);
		if (!info) {
			throw new errors.RecordsNoExists(`未找到录制信息：${meetingId},${uid}`);
		}
		let stoper = new Stop({ channelName, rid: info.rid, sid: info.sid, resourceId: info.resourceId }, this.modal);
		let ret = await stoper.run();
		await redisClient.deleteMeetingInfo(meetingId, uid);
		return ret;
	}

	async query(meetingId, uid) {
		let info = await this.getMeetingInfo(meetingId, uid);
		if (!info) {
			throw new errors.RecordsNoExists(`未找到录制信息：${meetingId},${uid}`);
		}
		let queryer = new Query({ resourceId: info.resourceId, sid: info.sid }, this.modal);
		return queryer.run();
	}

	async getMeetingInfo(meetingId, uid) {
		return redisClient.getMeetingInfo(meetingId, uid);
	}

	async getStartTime() {
		let { channelName, meetingId, uid } = this.args
		let key = `${channelName}-${uid}`
		let timeout = this._startTimeOut[key];
		if (!timeout) {
			this._startTimeOut[key] = timeout = { times: agora.getStartTimes };
		}
		if (timeout.times < 0) {
			throw new Error('timeout');
		}
		timeout.times--;
		return new Promise((resolve, reject) => {
			setTimeout(() => {
				this.query(meetingId, uid)
					.then(this._checkResponseFormat)
					.then(ret => {
						this.logger.info(`第${(agora.getStartTimes - timeout.times)}次获取sliceStartTime-${channelName}：${JSON.stringify(ret.serverResponse)}`)
						let res = ret.serverResponse;
						if (res.status === 5 && res.sliceStartTime !== 0) {
							delete this._startTimeOut[key];
							return ret;
						}
						if (exitStatus.includes(res.status)) {
							return reject(res.status)
						}
						return this.getStartTime(channelName, meetingId, uid);
					})
					.then(resolve).catch(reject);
			}, 4000)
		})
	}

	_checkResponseFormat(response) {
		let { serverResponse, resourceId } = response;
		let { fileListMode, fileList, status } = serverResponse;
		if (fileListMode !== 'json' || !fileList) {
			throw new errors.ResultFormat(response);
		}
		return response;
	}

}

module.exports = Recorder
